/**
 * @file    inf_cps121.c
 * @author  yhy
 * @brief   CPS121传感器源文件
 * @version 1.01
 * @date    2025-07-19
 *
 * @copyright Copyright (c) 2025
 *
 * @details
 * Change Logs:
 * Date           Author       Notes
 * 2025-07-19     yhy          the first version V1.00
 * 2025-10-22     yhy          修复了11个传感器只初始化了9个的问题 V1.01
 *
 */
#include "inf_cps121.h"

#include "common_debug.h"
#include "common_util.h"
#include "drv_gpio.h"
#include "drv_i2c_soft.h"
#include "drv_timer.h"

#define CPS121_BASE_ADDR  0x6C
#define CPS121_WRITE_ADDR ((CPS121_BASE_ADDR << 1) | 0)
#define CPS121_READ_ADDR  ((CPS121_BASE_ADDR << 1) | 1)

#define CPS121_MR_REG_ADDR 0x30
#define CPS121_MR_CMD      0x0A

#define CPS121_GD_REG_ADDR 0x06

static result_e inf_cps121_mrcmd(void);
static result_e inf_cps121_gdcmd(uint32_t *original_pressure);
static void     inf_cps121_init_sensor_list(void);
static result_e inf_cps121_i2c_init(void);
static result_e inf_cps121_timer_init(void);
static void     inf_cps121_machine(void);

/* CPS121-700传感器状态机索引 */
static uint8_t machine_idx = 0;

/* CPS121-700气压传感器列表 */
cps121_sensor_t cps121_sensor_list[CPS121_IDX_MAX];

/**
 * @brief 初始化CPS121-700气压传感器
 *
 * @return result_e   初始化结果
 */
result_e inf_cps121_init(void)
{
    inf_cps121_init_sensor_list();

    result_e result = inf_cps121_i2c_init();
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    return inf_cps121_timer_init();
}

/**
 * @brief 更新一次CPS121-700传感器的气压值
 *
 */
void inf_cps121_update_air_pressure(void)
{
    /* 启动定时器，开启状态机转换 */
    snf_drv_timer_start(TIMER_INSTANCE_TIMER0);
}

/**
 * @brief 初始化CPS121-700传感器需要的timer，用于状态机的调度
 *
 * @return result_e 初始化结果, 初始化成功返回RESULT_STATUS_OK, 初始化失败返回其他错误码
 */
static result_e inf_cps121_timer_init(void)
{
    /* 初始化timer, 5ms溢出一次 */
    snf_timer_config_t timer_config = {
        .instance      = TIMER_INSTANCE_TIMER0,
        .prescaler     = 29U - 1U,
        .compare_value = 200U - 1U,
        .callback      = inf_cps121_machine,
    };

    result_e result = snf_drv_timer_init(&timer_config);
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    /* 关闭timer, 因为初始化完timer后默认是开启的 */
    return snf_drv_timer_stop(TIMER_INSTANCE_TIMER0);
}

/**
 * @brief 初始化CPS121-700传感器的I2C接口
 *
 * @return result_e 初始化结果, 初始化成功返回RESULT_STATUS_OK, 初始化失败返回其他错误码
 */
static result_e inf_cps121_i2c_init(void)
{
    snf_i2c_soft_config_t i2c_config = {
        .scl_pin_num_list = { GET_PIN_NUM(D, 6), GET_PIN_NUM(D, 5), GET_PIN_NUM(C, 17), GET_PIN_NUM(C, 16),
                              GET_PIN_NUM(A, 13), GET_PIN_NUM(E, 6), GET_PIN_NUM(C, 5), GET_PIN_NUM(E, 0),
                              GET_PIN_NUM(E, 1), GET_PIN_NUM(A, 10), GET_PIN_NUM(A, 2) },
        .sda_pin_num      = GET_PIN_NUM(D, 1),
        .scl_count        = CPS121_IDX_MAX,
    };
    result_e ret = snf_drv_i2c_soft_init(&i2c_config);
    if (ret != RESULT_STATUS_OK) {
        return ret;
    }

    return RESULT_STATUS_OK;
}

/**
 * @brief 初始化CPS121-700传感器列表
 *
 */
static void inf_cps121_init_sensor_list(void)
{
    for (uint8_t i = 0; i < CPS121_IDX_MAX; i++) {
        cps121_sensor_list[i].sensor_idx   = (cps121_idx_e)i;
        cps121_sensor_list[i].air_pressure = 0U;
        cps121_sensor_list[i].state        = CPS121_STATE_IDLE;
    }
}

/**
 * @brief MR指令, 唤醒传感器，并将测量结果存在内部传感器, 发送指令后需要5ms以后才会有结果
 *
 * @return result_e 唤醒结果, 唤醒成功返回RESULT_STATUS_OK, 唤醒失败返回其他错误码
 */
static result_e inf_cps121_mrcmd(void)
{
    /* 1. 发送起始信号 */
    snf_drv_i2c_soft_start();

    /* 2. 发送从机地址 */
    snf_drv_i2c_soft_send_byte(CPS121_WRITE_ADDR);
    if (snf_drv_i2c_soft_wait4ack() == I2C_SOFT_RESP_NACK) {
        snf_drv_i2c_soft_stop();
        return RESULT_STATUS_I2C_WAIT_ACK_ERROR;
    }

    /* 3. 发送寄存器地址 */
    snf_drv_i2c_soft_send_byte(CPS121_MR_REG_ADDR);
    if (snf_drv_i2c_soft_wait4ack() == I2C_SOFT_RESP_NACK) {
        snf_drv_i2c_soft_stop();
        return RESULT_STATUS_I2C_WAIT_ACK_ERROR;
    }

    /* 4. 发送测量指令 */
    snf_drv_i2c_soft_send_byte(CPS121_MR_CMD);
    if (snf_drv_i2c_soft_wait4ack() == I2C_SOFT_RESP_NACK) {
        snf_drv_i2c_soft_stop();
        return RESULT_STATUS_I2C_WAIT_ACK_ERROR;
    }

    /* 5. 发送结束信号 */
    snf_drv_i2c_soft_stop();

    return RESULT_STATUS_OK;
}

/**
 * @brief 发送GD指令, 获取寄存器中的压力数据
 *
 * @param original_pressure 寄存器中原始的压力数据
 * @return result_e         获取结果
 */
static result_e inf_cps121_gdcmd(uint32_t *original_pressure)
{
    /* 1. 发送起始信号 */
    snf_drv_i2c_soft_start();

    /* 2. 发送从机地址 */
    snf_drv_i2c_soft_send_byte(CPS121_WRITE_ADDR);
    if (snf_drv_i2c_soft_wait4ack() == I2C_SOFT_RESP_NACK) {
        snf_drv_i2c_soft_stop();
        return RESULT_STATUS_I2C_WAIT_ACK_ERROR;
    }

    /* 3. 发送寄存器地址 */
    snf_drv_i2c_soft_send_byte(CPS121_GD_REG_ADDR);
    if (snf_drv_i2c_soft_wait4ack() == I2C_SOFT_RESP_NACK) {
        snf_drv_i2c_soft_stop();
        return RESULT_STATUS_I2C_WAIT_ACK_ERROR;
    }

    /* 4. 发送起始信号 */
    snf_drv_i2c_soft_start();

    /* 5. 发送从机读地址 */
    snf_drv_i2c_soft_send_byte(CPS121_READ_ADDR);
    if (snf_drv_i2c_soft_wait4ack() == I2C_SOFT_RESP_NACK) {
        snf_drv_i2c_soft_stop();
        return RESULT_STATUS_I2C_WAIT_ACK_ERROR;
    }

    /* 6. 读取数据 */
    uint32_t pressure = 0;
    pressure          = (uint32_t)snf_drv_i2c_soft_recv_byte() << 16; // 第一个字节 [23:16]
    snf_drv_i2c_soft_ack();

    pressure |= (uint32_t)snf_drv_i2c_soft_recv_byte() << 8;          // 第二个字节 [15:8]
    snf_drv_i2c_soft_ack();

    pressure |= (uint32_t)snf_drv_i2c_soft_recv_byte();               // 第三个字节 [7:0]
    snf_drv_i2c_soft_nack();

    /* 7. 发送结束信号 */
    snf_drv_i2c_soft_stop();

    *original_pressure = pressure;

    return RESULT_STATUS_OK;
}

/**
 * @brief CPS121-700传感器状态机
 *
 */
static void inf_cps121_machine(void)
{
    /* 检查是否所有传感器都已完成测量, 顺带进行数组越界检查 */
    if (machine_idx >= CPS121_IDX_MAX) {
        machine_idx = 0;
        snf_drv_timer_stop(TIMER_INSTANCE_TIMER0);
        snf_drv_i2c_soft_select_sclx(machine_idx);
        return;
    }

    if (cps121_sensor_list[machine_idx].state == CPS121_STATE_IDLE) {
        cps121_sensor_list[machine_idx].state = CPS121_STATE_BUSY;
        result_e result                       = inf_cps121_mrcmd();
        if (result != RESULT_STATUS_OK) {
            cps121_sensor_list[machine_idx].state = CPS121_STATE_IDLE;
            ++machine_idx;
            LOG("CPS121-700[%hhu] MR CMD error: %u\n", machine_idx, result);
        }
    }
    else {
        result_e result = inf_cps121_gdcmd(&cps121_sensor_list[machine_idx].air_pressure);
        if (result != RESULT_STATUS_OK) {
            LOG("CPS121-700[%hhu] GD CMD error: %u\n", machine_idx, result);
        }
        else {
            /* 将GD结果转换成真是气压只 */
            uint8_t byte3 = (cps121_sensor_list[machine_idx].air_pressure >> 16) & 0xFF; // [23:16]
            uint8_t byte2 = (cps121_sensor_list[machine_idx].air_pressure >> 8) & 0xFF;  // [15:8]
            uint8_t byte1 = cps121_sensor_list[machine_idx].air_pressure & 0xFF;         // [7:0]
            cps121_sensor_list[machine_idx].air_pressure =
                (uint32_t)(byte3 * 65536 + byte2 * 256 + byte1) / 8 / 1000;
        }

        /* 切换到下一个传感器 */
        cps121_sensor_list[machine_idx].state = CPS121_STATE_IDLE;
        ++machine_idx;
        snf_drv_i2c_soft_select_sclx(machine_idx);
    }
}
